package com.ncu.strategy.mode;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.ncu.domain.User;
import com.ncu.domain.UserRole;
import com.ncu.dto.SocialTokenDTO;
import com.ncu.dto.SocialUserInfoDTO;
import com.ncu.exception.BizException;
import com.ncu.mapper.MenuMapper;
import com.ncu.mapper.UserMapper;
import com.ncu.mapper.UserRoleMapper;
import com.ncu.pojo.LoginUser;
import com.ncu.service.UserService;
import com.ncu.strategy.SocialLoginStrategy;
import com.ncu.utils.*;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.ncu.constant.MessageConstant.USER_ABLE;
import static com.ncu.constant.RedisConst.LOGIN;


/**
 * 第三方登录抽象模板
 */
@Service
public abstract class AbstractSocialLoginStrategyImpl implements SocialLoginStrategy {
    @Resource
    private UserMapper userDao;
    @Resource
    private UserService userService;
    @Resource
    private UserRoleMapper tbUserRoleDao;

    @Resource
    private HttpServletRequest request;
//    @Resource
//    private SessionRegistry sessionRegistry;

    @Resource
    RedisCache redisCache;

    @Resource
    MenuMapper menuMapper;

    @Override
    public Map<String, Object> login(String data) {
        // 创建登录信息
        LoginUser userDetailDTO;
        // 获取第三方token信息
        SocialTokenDTO socialToken = getSocialToken(data);
        // 获取用户ip信息
        String ipAddress = IpUtils.getIpAddr(request);
        String ipSource = IpUtils.getIpSource(ipAddress);
        // 判断是否已注册
        User user = getUser(socialToken);
        //封装权限生成UserDetails的实现类LoginUser
        if (Objects.nonNull(user)) {
            // 返回数据库用户信息
            userDetailDTO = userService.getLoginUser(user, ipAddress, ipSource);
        } else {
            // 获取第三方用户信息，保存到数据库返回
            userDetailDTO = saveUserDetail(socialToken, ipAddress, ipSource);
        }
        // 判断账号是否禁用
        if (userDetailDTO.getUser().getStatus()==1) {
            throw new BizException("账号已被禁用");
        }

        // 将登录信息放入springSecurity管理
        UsernamePasswordAuthenticationToken auth =
                new UsernamePasswordAuthenticationToken(userDetailDTO, null, userDetailDTO.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(auth);

        //生成jwt
        String jwt = JwtUtil.createJWT((userDetailDTO.getUser().getId().toString()));

        //系统用户相关所有信息放入redis
        redisCache.setCacheObject(LOGIN+userDetailDTO.getUser().getId().toString(),userDetailDTO);

        Map<String,Object> map=new HashMap();
        map.put("user",userDetailDTO.getUser());
        map.put("token",jwt);
        return map;
    }

    /**
     * 获取第三方token信息
     *
     * @param data 数据
     * @return {@link SocialTokenDTO} 第三方token信息
     */
    public abstract SocialTokenDTO getSocialToken(String data);

    /**
     * 获取第三方用户信息
     *
     * @param socialTokenDTO 第三方token信息
     * @return {@link SocialUserInfoDTO} 第三方用户信息
     */
    public abstract SocialUserInfoDTO getSocialUserInfo(SocialTokenDTO socialTokenDTO);

    /**
     * 获取用户账号
     *
     * @return {@link User} 用户账号
     */
    private User getUser(SocialTokenDTO socialTokenDTO) {
        return userDao.selectOne(new LambdaQueryWrapper<User>()
                .eq(User::getUserName, socialTokenDTO.getOpenId())
                .eq(User::getLoginType, socialTokenDTO.getLoginType()));
    }

    /**
     * 新增用户信息
     *
     * @param socialToken token信息
     * @param ipAddress   ip地址
     * @param ipSource    ip源
     * @return {@link LoginUser} 用户信息
     */
    private LoginUser saveUserDetail(SocialTokenDTO socialToken, String ipAddress, String ipSource) {
        // 获取第三方用户信息
        SocialUserInfoDTO socialUserInfo = getSocialUserInfo(socialToken);
        // 保存用户信息
        User user = User.builder()
                .nickName(socialUserInfo.getNickname())
                .avatar(socialUserInfo.getAvatar())
                .id(IdWorker.getId(User.class))
                .userName(socialToken.getOpenId())
                .password(socialToken.getAccessToken())
                .loginType(socialToken.getLoginType())
                .lastTime(LocalDateTime.now())
                .lastIp(ipAddress)
                .status(USER_ABLE)
                .ipSource(ipSource)
                .build();
        userDao.insert(user);
        UserRole userRole = UserRole.builder()
                .userId(user.getId())
                .roleId(2L)
                .build();
        tbUserRoleDao.insert(userRole);
        List<String> perms = menuMapper.selectPermsByUserId(user.getId());
        System.out.println(perms);
        //封装成UserDetails对象返回
        return new LoginUser(user,perms);
    }


}
